package za.co.ray.oxm.jdk;

import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;

import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;

import org.apache.commons.io.input.ReaderInputStream;
import org.apache.commons.io.output.WriterOutputStream;
import org.springframework.oxm.XmlMappingException;
import org.springframework.oxm.support.AbstractMarshaller;
import org.springframework.util.xml.DomUtils;
import org.springframework.util.xml.StaxUtils;
import org.w3c.dom.Node;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.ext.LexicalHandler;

public class JdkXmlMarsheller extends AbstractMarshaller {

    @Override
    public boolean supports(Class<?> clazz) {

        return true;
    }

    @Override
    protected void marshalDomNode(Object graph, Node node) throws XmlMappingException {
        marshalSaxHandlers(graph, DomUtils.createContentHandler(node), null);

    }

    @Override
    protected void marshalXmlEventWriter(Object graph, XMLEventWriter eventWriter) throws XmlMappingException {
        marshalSaxHandlers(graph, StaxUtils.createContentHandler(eventWriter), null);

    }

    @Override
    protected void marshalXmlStreamWriter(Object graph, XMLStreamWriter streamWriter) throws XmlMappingException {
        marshalSaxHandlers(graph, StaxUtils.createContentHandler(streamWriter), null);

    }

    @Override
    protected void marshalOutputStream(Object graph, OutputStream outputStream) throws XmlMappingException, IOException {

        XMLEncoder e = null;
        try {
            e = new XMLEncoder(outputStream);

            e.writeObject(graph);

        } catch (IllegalArgumentException e2) {
            throw new IOException(e2);
        } catch (Exception e2) {
            throw new JdkMappingException(e2.getMessage(), e2);
        } finally {
            if (e != null) {
                e.close();
            }
        }

    }

    @Override
    protected void marshalSaxHandlers(Object graph, ContentHandler contentHandler, LexicalHandler lexicalHandler) throws XmlMappingException {
        throw new IllegalArgumentException("Not implemented");

    }

    @Override
    protected void marshalWriter(Object graph, Writer writer) throws XmlMappingException, IOException {
        marshalOutputStream(graph, new WriterOutputStream(writer));
    }

    @Override
    protected Object unmarshalDomNode(Node node) throws XmlMappingException {
        throw new IllegalArgumentException("Not implemented");
    }

    @Override
    protected Object unmarshalXmlEventReader(XMLEventReader eventReader) throws XmlMappingException {
        throw new IllegalArgumentException("Not implemented");
    }

    @Override
    protected Object unmarshalXmlStreamReader(XMLStreamReader streamReader) throws XmlMappingException {
        throw new IllegalArgumentException("Not implemented");
    }

    @Override
    protected Object unmarshalInputStream(InputStream inputStream) throws XmlMappingException, IOException {

        XMLDecoder d = null;
        
        try {
            d = new XMLDecoder(new BufferedInputStream(inputStream));
            Object result = d.readObject();
            return result;
        } catch (Exception e) {
            throw new JdkMappingException(e.getMessage(), e);
        } finally {
            d.close();    
        }

    }

    @Override
    protected Object unmarshalReader(Reader reader) throws XmlMappingException, IOException {
        return unmarshalInputStream(new ReaderInputStream(reader));
    }

    @Override
    protected Object unmarshalSaxReader(XMLReader xmlReader, InputSource inputSource) throws XmlMappingException, IOException {
        throw new IllegalArgumentException("Not implemented");
    }



}
